一个flash xss的利用

从几个星期前就心心念念找一个flash xss来玩,现在flash用的比较少了,自己也懒得每开一个页面就看下有没有swf文件加载进来,于是就简单写了个油猴脚本辅助检测。思路是用的EtherDream大神在微博说的获取所有请求的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
(function() {
setTimeout(function(){
var urls = performance.getEntries()
have_flash = false;
urls.forEach(function(e){
if(e.name.indexOf(".swf") !== -1){
have_flash = true;
console.warn("%c"+location.hostname+' 发现Flash:'+e.name,"color:red;font-size:13px");
}
})
if(have_flash) alert("Flash found!");
}, 5000)
})()

最后在某网站找到一个预览文档的flash文件。
http://5alt.com/flash/vul.swf?attachment_id=109246&base_url=http://5alt.com/&nick=5alt&place=&reference=http://5alt.me/233
在文档预览的时候,flash会发送请求获取一个新的swf文件作为文档的数据加载进来。
从flash请求的参数上来看就知道这个flash非常可疑。用JPEXS反编译可得到如下关键代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
var g_base_url = !_root.base_url;
...
function loadSlide(slideIndex)
{
sessionLV.sendAndLoad(g_base_url + "apis/ppt_viewer/data.php",timeLV,"GET");
timeLV.onLoad = function(success)
{
if(success)
{
time = timeLV.number;
var _loc1_ = encryption.hash(private_key + g_fileName + time);
get_swf_file(slideIndex,_loc1_);
}
};
}
function get_swf_file(slideIndex, key)
{
var _loc4_ = "swf/" + g_fileName + slideIndex + ".swf";
var _loc3_ = g_base_url + "apis/ppt_viewer/data.php?page=" + slideIndex + "&filename=" + g_fileName + "&id=" + g_attachment_id + "&key=" + key;
var _loc2_ = new MovieClipLoader();
_loc2_.addListener(this);
if(g_currentPageloadNo % 2 == 0)
{
_loc2_.loadClip(_loc3_,this.evenSliderMC);
}
else
{
_loc2_.loadClip(_loc3_,this.oddSliderMC);
}
}
resultLV.onLoad = function(success)
{
if(success)
{
...
loadSlide(1);
}
};

总结一下就是swf加载完成后会去远程获取一个文件加载成为一个新的MovieClip。加载文件的url为g_base_url然后拼接上一个固定的地址,g_base_url即为参数base_url。
因此我们可以通过控制base_url来让这个flash加载我们指定的swf文件,从而触发xss。

思路有了,接下来开始模拟环境进行测试。
首先遇到第一个坑,自己编写的swf文件无法加载运行。我自己对flash不太熟,也不知道怎么编写一个可以被加载运行的swf文件,于是选择从可以加载作为文档数据的swf入手。
然后遇到第二个坑,用burpsuite抓的包解码保存成swf文件是坏掉的,调了半天也不知道为什么,用wireshark抓出来的swf就是好的。
JPEXS有个黑科技,可以修改反编译出来的actionscript代码然后打包回去。于是在抓到合法的swf文件基础上加上了一段测试用的执行js的代码。

1
flash.external.ExternalInterface.call("eval","alert(document.domain)");

在测试的时候,将有问题的swf文件和后来加载的swf文件都放在本地的server上,测试可以弹窗,但是如果这两个文件域不一样的话,js就不能执行。这里又有一个flash域的坑。
加载不同域上的swf文件不能执行js,于是就想办法变成同域。网站正好有上传图片的功能,将插好恶意代码的swf文件改后缀成png传上去发现内容没有被修改,这样就有了一个同域的swf文件。然后就是想办法加载这个swf文件了。

由于我们只能控制base_url,而不能控制后面的路径,所以只能想办法将加载swf的请求跳转到上传后的文件上去。在这里可以自己搭建一个server,302跳转过去。

于是就可以愉快的弹窗了。

当然,利用这个网站上传图片不修改内容的特点,还可以用flash获取站点网页的内容。详细见irsdl的poc

参考文档

https://www.secpulse.com/archives/44299.html
https://www.cnblogs.com/index-html/p/swf-reflect-priv.html
https://github.com/evilcos/papers/blob/master/%E9%9A%90%E8%94%BD%E7%9A%84%E6%88%98%E5%9C%BA%E2%80%94Flash%20Web%E6%94%BB%E5%87%BB.pptx
https://xianzhi.aliyun.com/forum/read/224.html

分享到 评论